package models

import (
	"LoveU/utils"
	"strconv"

	"github.com/astaxie/beego/orm"
)

//处理城市位置

const PROVINCE = 10000
const COUNTRY = 100

// 将字符串形式的三段行政区划编号，转换为int64（status表示是否都成功转换）
func transformCodes(prov,city,county string) (bool,int64,int64,int64) {
	province_int, err0 := strconv.ParseInt(prov, 10, 64)
	country_int, err1 := strconv.ParseInt(city, 10, 64)
	county_int, err2 := strconv.ParseInt(county, 10, 64)
	status := (err0 == nil && err1 == nil && err2 == nil)
	return status,province_int,country_int,county_int
}

// 根据ID返回唯一对应的地区代码、名称。返回值：
// utils.AREA_CODE_NOT_FOUND,nil
// utils.UNKNOWN_ERROR,nil
// utils.AREA_CODE_OK,一个*Area实例
func GetAreaById(id int64) (int64,*Area) {
	o := orm.NewOrm()
	qs := o.QueryTable("area")
	area := new(Area)
	err := qs.Filter("id",id).One(area)
	if err==orm.ErrNoRows {
		return utils.AREA_CODE_NOT_FOUND,nil
	} else if err!=nil {
		return utils.UNKNOWN_ERROR,nil
	}
	return utils.AREA_CODE_OK,area
}

// 根据ID返回唯一对应的地区代码、名称。返回值：
// utils.AREA_CODE_NOT_FOUND,nil
// utils.ARGUMENT_DENIED,nil
// utils.UNKNOWN_ERROR,nil
// utils.AREA_CODE_OK,一个*Area实例
func GetAreaByCode(province, country, county string) (int64,*Area) {
	o := orm.NewOrm()
	qs := o.QueryTable("area")
	area := new(Area)
	passed,province_int,country_int,county_int := transformCodes(province,country,county)
	if passed==false {
		return utils.ARGUMENT_DENIED,nil
	}
	err := qs.Filter("province", province_int).Filter("country", country_int).Filter("county", county_int).One(area)
	if err == nil {
		return utils.AREA_CODE_OK,area
	} else if err==orm.ErrNoRows {
		return utils.AREA_CODE_NOT_FOUND,nil
	} else {
		return utils.UNKNOWN_ERROR,nil
	}
}

// 返回值：
// utils.ARGUMENT_DENIED
// utils.UNKNOWN_ERROR
// utils.AREA_CODE_OK
func GetAreaId(province, country, county string) (int64, int64) {
	o := orm.NewOrm()
	qs := o.QueryTable("area")
	area := new(Area)
	passed,province_int,country_int,county_int := transformCodes(province,country,county)
	if passed==false {
		return -1, utils.ARGUMENT_DENIED
	}
	err := qs.Filter("province", province_int).Filter("country", country_int).Filter("county", county_int).One(area)
	if err != nil {
		return -1, utils.UNKNOWN_ERROR
	}
	return area.Id, utils.AREA_CODE_OK
}

// 获取（服务器记录的）全国省份（市、区），或该省的所有地级市，或该市的所有县级单位
// 【注意】若province为"0"、country不为"0"，或两项均为空，则返回所有地名记录
func GetAreas(province,country string) (int64,[]*Area) {
	passed,province_int,country_int,_ := transformCodes(province,country,"0")
	if passed==false {
		return utils.ARGUMENT_DENIED,nil
	}
	o := orm.NewOrm()
	qs := o.QueryTable("area")
	//直辖市的省级代码
	MUNICIPALITIES := []int64{11,12,31,50,81,82}
	if province_int == 0 && country_int == 0 {
		//返回省份、直辖市、自治区、特别行政区
		qs = qs.Filter("country",0).Filter("county",0)
	} else if country_int == 0 {
		var munFound int = -1
		for count,municipality := range MUNICIPALITIES {
			if province_int == municipality {
				munFound = count
				break
			}
		}
		if munFound != -1 {
			//该单位是直辖市或特别行政区，返回市、区名
			qs = qs.Filter("province",province_int).Filter("country",0).Filter("county",0)
		} else {
			//该单位是省、自治区，返回其所有地级市
			qs = qs.Filter("province",province_int).Exclude("country",0).Filter("county",0)
		}
	} else if province_int != 0 {
		//返回该市的所有县级单位
		var munFound int = -1
		for count,municipality := range MUNICIPALITIES {
			if province_int == municipality {
				munFound = count
				break
			}
		}
		if munFound != -1 {
			//该单位是直辖市或特别行政区
			qs = qs.Filter("province",province_int).Filter("country",1)
		} else {
			//该单位是地级市
			qs = qs.Filter("province",province_int).Filter("country",country_int).Exclude("county",0)
		}
	}
	// 对于province_int == 0 && country_int != 0，返回所有记录
	areas := make([]*Area,0)
	_, err := qs.Limit(-1).All(&areas,"province","country","county","name")
	if err!=nil {
		return utils.DATABASE_ERROR,nil
	}
	return utils.OK,areas
}

// 获得某地区的三级代码、名称（无返回）
func GetAreaNames(result *AreaResult, source *Area) {
	if source.Country!=0 {
		provinceStr := strconv.FormatInt(source.Province,10)
		countryStr := strconv.FormatInt(source.Country,10)
		if source.County!=0 {
			status2,cityInfo := GetAreaByCode(provinceStr,countryStr,"0")
			if status2==utils.AREA_CODE_OK {
				result.Country = cityInfo.Name
			}
			result.County = source.Name
		} else {
			result.Country = source.Name
		}
		status1,provInfo := GetAreaByCode(provinceStr,"0","0")
		if status1==utils.AREA_CODE_OK {
			result.Province = provInfo.Name
		}
	} else {
		result.Province = source.Name
	}
}